import junit.framework.TestCase;
import org.biojava3.alignment.Alignments;
import org.biojava3.alignment.template.AlignedSequence;
import org.biojava3.alignment.template.Profile;
import org.biojava3.core.exceptions.CompoundNotFoundError;
import org.biojava3.core.exceptions.TranslationException;
import org.biojava3.core.sequence.DNASequence;
import org.biojava3.core.sequence.ProteinSequence;
import org.biojava3.core.sequence.RNASequence;
import org.biojava3.core.sequence.compound.AminoAcidCompound;
import org.biojava3.core.util.ConcurrencyTools;
import org.junit.Test;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * Author: Oleg Yasnev (oyasnev@gmail.com)
 * Date: 06.05.14
 */
public class MainTest extends TestCase {

    public MainTest() {

    }

    @Test
    public void testReadSeqFromFile() throws Exception {
        LinkedHashMap<String, DNASequence> seqMap = Main.readSeqFromFile("test.fasta");
        assertEquals(1, seqMap.size());
        DNASequence dna = seqMap.get("TestSeq");
        assertNotNull(dna);
        assertEquals("TestSeq", dna.getOriginalHeader());
        assertEquals("AAAACCCCGGGGTTTT", dna.getSequenceAsString());

        try {
            Main.readSeqFromFile("test.txt");
            fail("Exception expected");
        } catch (Exception e) {
        }
    }

    @Test
    public void testGetGCContent() throws Exception {
        DNASequence dna;
        dna = new DNASequence("ACGT");
        assertEquals(50.0, Main.getGCContent(dna), 0.001);
        dna = new DNASequence("CGCG");
        assertEquals(100.0, Main.getGCContent(dna), 0.001);
        dna = new DNASequence("ATTA");
        assertEquals(0.0, Main.getGCContent(dna), 0.001);
    }

    @Test
     public void testRNATranscription() throws Exception {
        DNASequence dna;
        dna = new DNASequence("ACGT");
        assertEquals("ACGU", dna.getRNASequence().getSequenceAsString());
        dna = new DNASequence("AAA");
        assertEquals("AAA", dna.getRNASequence().getSequenceAsString());
        dna = new DNASequence("CCC");
        assertEquals("CCC", dna.getRNASequence().getSequenceAsString());
        dna = new DNASequence("GGG");
        assertEquals("GGG", dna.getRNASequence().getSequenceAsString());
        dna = new DNASequence("TTT");
        assertEquals("UUU", dna.getRNASequence().getSequenceAsString());

        try {
            new DNASequence("ZZZ");
            fail("CompoundNotFoundError expected");
        } catch (Error e) {
            assertTrue(e instanceof CompoundNotFoundError);
        }
    }

    @Test
    public void testProteinTranslation() throws Exception {
        RNASequence rna;
        rna = new RNASequence("AUG");
        assertEquals("M", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("UUUUUCUUAUUGCUUCUCCUACUG");
        assertEquals("FFLLLLLL", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("AUUAUCAUAAUGGUUGUCGUAGUG");
        assertEquals("IIIMVVVV", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("UCUUCCUCAUCGCCUCCCCCACCG");
        assertEquals("SSSSPPPP", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("ACUACCACAACGGCUGCCGCAGCG");
        assertEquals("TTTTAAAA", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("UAUUACCAUCACCAACAGAAUAAC");
        assertEquals("YYHHQQNN", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("AAAAAGGAUGACGAAGAGUGUUGC");
        assertEquals("KKDDEECC", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("UGGCGUCGCCGACGGAGUAGC");
        assertEquals("WRRRRSS", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("AGAAGGGGUGGCGGAGGG");
        assertEquals("RRGGGG", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("AUGUAA");
        assertEquals("M", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("AUGUAG");
        assertEquals("M", rna.getProteinSequence().getSequenceAsString());
        rna = new RNASequence("AUGUGA");
        assertEquals("M", rna.getProteinSequence().getSequenceAsString());

        rna = new RNASequence("A");
        try {
            rna.getProteinSequence();
            fail("TranslationException expected");
        } catch (Exception e) {
            assertTrue(e instanceof TranslationException);
        }
        rna = new RNASequence("AA");
        try {
            rna.getProteinSequence();
            fail("TranslationException expected");
        } catch (Exception e) {
            assertTrue(e instanceof TranslationException);
        }

        try {
            new RNASequence("ZZZ");
            fail("CompoundNotFoundError expected");
        } catch (Error e) {
            assertTrue(e instanceof CompoundNotFoundError);
        }
    }

    @Test
    public void testMultipleAlignment() throws Exception {
        List<ProteinSequence> proteinList = new ArrayList<ProteinSequence>();
        Profile<ProteinSequence, AminoAcidCompound> profile;

        String s = "MAMAPRTEIN";
        proteinList.add(new ProteinSequence(s));
        proteinList.add(new ProteinSequence(s));
        proteinList.add(new ProteinSequence(s));
        profile = Alignments.getMultipleSequenceAlignment(proteinList);
        ConcurrencyTools.shutdown();
        for (AlignedSequence<ProteinSequence, AminoAcidCompound> seq : profile) {
            assertEquals(s, seq.getSequenceAsString());
        }

        proteinList.clear();
        proteinList.add(new ProteinSequence(s));
        proteinList.add(new ProteinSequence(s));
        proteinList.add(new ProteinSequence("MAMAPRFTEIN"));
        profile = Alignments.getMultipleSequenceAlignment(proteinList);
        ConcurrencyTools.shutdown();
        assertEquals("MAMAPR-TEIN", profile.getAlignedSequence(1).getSequenceAsString());
        assertEquals("MAMAPR-TEIN", profile.getAlignedSequence(2).getSequenceAsString());
        assertEquals("MAMAPRFTEIN", profile.getAlignedSequence(3).getSequenceAsString());
    }
}
